/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | foam-extend: Open Source CFD
   \\    /   O peration     | Version:     4.1
    \\  /    A nd           | Web:         http://www.foam-extend.org
     \\/     M anipulation  | For copyright notice see file Copyright
-------------------------------------------------------------------------------
License
	This file is part of foam-extend.

	foam-extend is free software: you can redistribute it and/or modify it
	under the terms of the GNU General Public License as published by the
	Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	foam-extend is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.

Class
	Foam::PtrList

Description
	A templated 1D list of pointers to objects of type \<T\>, where the
	size of the array is known and used for subscript bounds checking, etc.

	The element operator [] returns a reference to the object
	rather than to the pointer.

SourceFiles
	PtrList.C
	PtrListIO.C

\*---------------------------------------------------------------------------*/

#ifndef PtrList_H
#define PtrList_H

#include "List.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

namespace Foam
{

// Forward declaration of friend functions and operators

template<class T> class PtrList;
template<class T> class SLPtrList;

template<class T>
inline typename PtrList<T>::iterator operator+
(
	const typename PtrList<T>::iterator&,
	label
);

template<class T>
inline typename PtrList<T>::iterator operator+
(
	label,
	const typename PtrList<T>::iterator&
);

template<class T>
inline typename PtrList<T>::iterator operator-
(
	const typename PtrList<T>::iterator&,
	label
);

template<class T>
inline label operator-
(
	const typename PtrList<T>::iterator&,
	const typename PtrList<T>::iterator&
);

template<class T>
Istream& operator>>(Istream&, PtrList<T>&);

template<class T>
Ostream& operator<<(Ostream&, const PtrList<T>&);

template<class T> class autoPtr;
template<class T> class tmp;



template<class T>
class PtrList
{
	// Private data

		List<T*> ptrs_;


protected:

	// Protected member functions

		//- Read from Istream using given Istream constructor class
		template<class INew>
		void read(Istream&, const INew& inewt);


public:

	// Constructors

		//- Null Constructor.
		PtrList();

		//- Construct with length specified.
		explicit PtrList(const label);

		//- Copy constructor.
		PtrList(const PtrList<T>&);

		//- Copy constructor with additional argument for clone
		template<class CloneArg>
		PtrList(const PtrList<T>&, const CloneArg&);

		//- Construct by transferring the parameter contents
		PtrList(const Xfer<PtrList<T> >&);

		//- Construct as copy or re-use as specified.
		PtrList(PtrList<T>&, bool reUse);

		//- Construct as copy of SLPtrList<T>
		PtrList(const SLPtrList<T>&);

		//- Construct from Istream using given Istream constructor class
		template<class INew>
		PtrList(Istream&, const INew&);

		//- Construct from Istream using default Istream constructor class
		PtrList(Istream&);


	//- Destructor
	~PtrList();


	// Member functions

		// Access

			//- Return the number of elements in the PtrList
			inline label size() const;

			//- Return true if the PtrList is empty (ie, size() is zero).
			inline bool empty() const;


		// Edit

			//- Reset size of PtrList.  This can only be used to set the size
			//  of an empty PtrList, extend a PtrList, remove entries from
			//  the end of a PtrList. If the entries are non-empty they are
			//  deleted.
			void setSize(const label);

			//- Reset size of PtrList.  This can only be used to set the size
			//  of an empty PtrList, extend a PtrList, remove entries from
			//  the end of a PtrList. If the entries are non-empty they are
			//  deleted.
			inline void resize(const label);

			//- Clear the PtrList, i.e. set size to zero deleting all the
			//  allocated entries.
			void clear();

			//- Transfer the contents of the argument PtrList into this PtrList
			//  and annull the argument list.
			void transfer(PtrList<T>&);

			//- Transfer contents to the Xfer container
			inline Xfer<PtrList<T> > xfer();

			//- Is element set
			inline bool set(const label) const;

			//- Set element. Return old element (can be nullptr).
			//  No checks on new element.
			inline autoPtr<T> set(const label, T*);
			inline autoPtr<T> set(const label, const autoPtr<T>&);
			inline autoPtr<T> set(const label, const tmp<T>&);

			//- Reorders elements. Ordering does not have to be done in
			//  ascending or descending order. Reordering has to be unique.
			//  (is shuffle)
			void reorder(const UList<label>&);


	// Member operators

		//- Return element const reference.
		inline const T& operator[](const label) const;

		//- Return element reference.
		inline T& operator[](const label);

		//- Return element const pointer.
		inline const T* operator()(const label) const;


		//- Assignment.
		PtrList<T>& operator=(const PtrList<T>&);


	// STL type definitions

		//- Type of values the PtrList contains.
		typedef T value_type;

		//- Type that can be used for storing into PtrList::value_type objects.
		typedef T& reference;

		//- Type that can be used for storing into constant PtrList::value_type
		//  objects.
		typedef const T& const_reference;


	// STL iterator
	// Random access iterator for traversing PtrList.

		class iterator;
		friend class iterator;

		//- An STL-conforming iterator
		class iterator
		{
			T** ptr_;

		public:

			//- Construct for a given PtrList entry
			inline iterator(T**);

			// Member operators

				inline bool operator==(const iterator&) const;
				inline bool operator!=(const iterator&) const;

				typedef T& Tref;
				inline Tref operator*();
				inline Tref operator()();

				inline iterator operator++();
				inline iterator operator++(int);

				inline iterator operator--();
				inline iterator operator--(int);

				inline iterator operator+=(label);

				friend iterator operator+ <T>(const iterator&, label);
				friend iterator operator+ <T>(label, const iterator&);

				inline iterator operator-=(label);

				friend iterator operator- <T>(const iterator&, label);

				friend label operator- <T>
				(
					const iterator&,
					const iterator&
				);

				inline T& operator[](label);

				inline bool operator<(const iterator&) const;
				inline bool operator>(const iterator&) const;

				inline bool operator<=(const iterator&) const;
				inline bool operator>=(const iterator&) const;
		};

		//- Return an iterator to begin traversing the PtrList.
		inline iterator begin();

		//- Return an iterator to end traversing the PtrList.
		inline iterator end();


	// IOstream operator

		//- Read List from Istream, discarding contents of existing List.
		friend Istream& operator>> <T>(Istream&, PtrList<T>&);

		// Write List to Ostream.
		friend Ostream& operator<< <T>(Ostream&, const PtrList<T>&);
};


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

} // End namespace Foam

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#	include "PtrListI.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#ifdef NoRepository
#	include "PtrList.C"
#endif

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#endif

// ************************************************************************* //
